package com.weme.common.view

import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import androidx.constraintlayout.widget.ConstraintLayout
import com.weme.common.R

class SmoothConstraintLayout @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr) {
    private var paint: Paint = Paint(Paint.ANTI_ALIAS_FLAG)
    private var path: Path = Path()
    private var rectF: RectF = RectF()
    var roundPath: SmootRoundedPath = SmootRoundedPath()
    private var leftRadius = 0F
    private var rightRadius = 0F
    private var topRadius = 0F
    private var bottomRadius = 0F
    var rectColor = Color.WHITE
    var endColor = 0
    private var drawBorderOnly = false
    private var strokeWidth = 2F
    private var startColor = Color.WHITE
    private var gradientOrientation: Int = -1

    init {
        val a = context.obtainStyledAttributes(attrs, R.styleable.SmoothRoundedRectView, defStyleAttr, 0)
        val cornerRadius = a.getDimensionPixelSize(R.styleable.SmoothRoundedRectView_radius, -1)
        leftRadius = a.getDimensionPixelSize(R.styleable.SmoothRoundedRectView_rightTopRadius, cornerRadius).toFloat()
        rightRadius = a.getDimensionPixelSize(R.styleable.SmoothRoundedRectView_leftBottomRadius, cornerRadius).toFloat()
        topRadius = a.getDimensionPixelSize(R.styleable.SmoothRoundedRectView_rightBottomRadius, cornerRadius).toFloat()
        bottomRadius = a.getDimensionPixelSize(R.styleable.SmoothRoundedRectView_leftTopRadius, cornerRadius).toFloat()
        rectColor = a.getColor(R.styleable.SmoothRoundedRectView_rectColor, Color.WHITE)
        drawBorderOnly = a.getBoolean(R.styleable.SmoothRoundedRectView_drawBorderOnly, false)
        strokeWidth = a.getDimensionPixelSize(R.styleable.SmoothRoundedRectView_strokeWidth, 2).toFloat()
        startColor = a.getColor(R.styleable.SmoothRoundedRectView_smoothStartColor, Color.WHITE)
        endColor = a.getColor(R.styleable.SmoothRoundedRectView_smoothEndColor, 0)
        gradientOrientation = a.getInt(R.styleable.SmoothRoundedRectView_gradientOrientations, -1)
        a.recycle()
        init()
    }

    private fun init() {

        paint.color = rectColor
        setWillNotDraw(false)
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        updateGradient(w, h)
    }

    private fun updateGradient(width: Int, height: Int) {
        if (startColor != endColor && endColor != 0) {
            val gradient = LinearGradient(
                0f, 0f,
                if (gradientOrientation == 0) width.toFloat() else 0f,
                if (gradientOrientation == 1) height.toFloat() else 0f,
                startColor, endColor, Shader.TileMode.CLAMP
            )
            paint.shader = gradient
        } else {
            paint.shader = null
            paint.color = rectColor
        }
    }

    fun setDrawBorderOnly(drawBorderOnly: Boolean) {
        this.drawBorderOnly = drawBorderOnly
        invalidate()
    }

    fun setColor(rectColor: Int, endColor: Int = 0) {
        paint.color = rectColor
        this.endColor = endColor
        invalidate()
    }

    fun setRounde(progress: Int) {
        roundPath.proportion = progress.toFloat()
        invalidate()
    }

    fun setRoundeing(progress: Int) {
        roundPath.proportion = progress.toFloat()
        invalidate()
    }

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)

        paint.isAntiAlias = true
        if (leftRadius == -1F) leftRadius = (height / 5).toFloat()
        if (topRadius == -1F) topRadius = (height / 5).toFloat()
        if (rightRadius == -1F) rightRadius = (height / 5).toFloat()
        if (bottomRadius == -1F) bottomRadius = (height / 5).toFloat()

        rectF[0f, 0f, width.toFloat()] = height.toFloat()

        path = roundPath.getSmoothRoundPath(rectF, leftRadius.coerceAtLeast(0f), topRadius.coerceAtLeast(0f), rightRadius.coerceAtLeast(0f), bottomRadius.coerceAtLeast(0f))

        // Check and set gradient
        updateGradient(width, height)

        paint.style = if (drawBorderOnly) Paint.Style.STROKE else Paint.Style.FILL

        canvas?.drawPath(path, paint)
    }
}
